//
// Created by LiuYou on 2021/6/26.
//
/**
 * @brief 将多线程并发改为多进程并发。
 */

#include <cstdlib>
#include <cstdio>
#include <unistd.h>
#include <sys/wait.h>


#define PROC_NUM         20
#define FILE_NAME       "/tmp/out"
#define LINE_SIZE       1024


// TODO 注意: 每个线程要做的工作, 即每个线程要完成的任务。
// TODO 注意: 现在变成了每个进程要做的工作。
static void* func() {
    FILE* fp = std::fopen( FILE_NAME, "r+" );
    if (fp == nullptr) {
        std::perror( "fopen()" );
        std::exit( EXIT_FAILURE );
    }

    char lineBuf[LINE_SIZE]{};

    // 将文件流变为文件描述符。
    int fd = fileno( fp );
    lockf( fd, F_LOCK, 0 );

    char* string = std::fgets( lineBuf, LINE_SIZE, fp );
    // 对 std::fgets()函数的返回值进行判断。这里就不写了。
//    if () {
//
//    }


    std::fseek( fp, 0, SEEK_SET );

    sleep( 1 );

    std::fprintf( fp, "%d\n", std::atoi( lineBuf ) + 1 );
    fflush( fp );

    lockf( fd, F_ULOCK, 0 );
    std::fclose( fp );
    return nullptr;
}

/**
 * @brief 为 add例子加入的互斥量。
 * 可以正确运行得出正确的结果。
 */
int main() {

    pthread_t tid[PROC_NUM]{};

    for (int i = 0; i < PROC_NUM; ++i) {
        pid_t pid = fork();
        if (pid < 0) {
            std::perror( "fork()" );
            std::exit( 1 );
        }
        if (pid == 0) {
            func();
            exit( 0 );
        }
    }

    // 收尸环节
    for (unsigned long i : tid) {
        wait( nullptr );
    }


    std::exit( EXIT_SUCCESS );
}